From 61ad849ac21e244aa50a0448212cb92c6e6ae40e Mon Sep 17 00:00:00 2001 From: oliskoli Date: Sat, 22 Oct 2005 19:45:11 +0000 Subject: [PATCH] Made a couple of cotoGPS fixes to get this format back --- gpsbabel/README | 22 +++ gpsbabel/coto.c | 243 ++++++++++++++------------ gpsbabel/reference/cototestmarker.gpx | 8 +- gpsbabel/testo | 22 +-- gpsbabel/vecs.c | 2 - 5 files changed, 173 insertions(+), 124 deletions(-) diff --git a/gpsbabel/README b/gpsbabel/README index 17493f49e..02d8d3522 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -1084,6 +1084,7 @@ THE FORMATS -F a_to_b.bcr OPENOFFICE + Tab seperated export-all (except geocaching data) file format. Intended to serve as source for number-processing applications like OpenOffice, Ploticus and others. Tab was chosen as delimiter @@ -1092,6 +1093,27 @@ THE FORMATS it to locales where ',' is used as decimal seperator. Contributed by Tobias Minich. + COTO + + Format for cotoGPS, a Palm GPS program. It can read both + track and marker (waypoint) files. It is currently unable + to write track files, so only marker files can be written. The + marker categories are written to and read from the icon + description. The 'Not Assigned' category leaves the icon + description empty on read. Currently geocache info is ignored. + + Options: + + zerocat (output) - Name for the Palm 'Not Assigned' category. + Defaults to 'Not Assigned'. + There is also a debugging option called 'internals' which + takes a XCSV delimiter value. It writes some internal + values (distance, arc, x and y) of the cotoGPS track + format to the notes field. + + URL: http://core.de/~coto/projects/cotogps/ + Contributed by Tobias Minich. + GEOnet Input support for the GEOnet Names Server (GNS) country file diff --git a/gpsbabel/coto.c b/gpsbabel/coto.c index 1ccb4673b..d3d363b08 100644 --- a/gpsbabel/coto.c +++ b/gpsbabel/coto.c @@ -1,7 +1,7 @@ /* - Read and write Coto files. + Read and write cotoGPS files. - Copyright (C) 2005 Tobias Minich, robertlipe@usa.net + Copyright (C) 2005 Tobias Minich, Based on the Cetus I/O Filter, Copyright (C) 2002 Robert Lipe, robertlipe@usa.net @@ -28,19 +28,23 @@ #include "coldsync/pdb.h" #define MYNAME "cotoGPS" + #define MYTYPETRACK 0x5452434b /* TRCK */ #define MYTYPEWPT 0x44415441 /* DATA */ -#define MYCREATOR 0x636f4750 /* coGP */ +#define MYCREATOR 0x636f4750 /* coGP */ #define NOTESZ 4096 #define DESCSZ 4096 +#define MAX_MARKER_NAME_LENGTH 20 +#define CATEGORY_NAME_LENGTH 16 + typedef enum { - cotofixNone = 0, /* No Fix or Warning */ + cotofixNone = 0, /* No Fix or Warning */ cotofixReserved = 1, /* Shouldn't occur*/ - cotofix2D = 2, /* retrieved from a GPS with a 2D fix */ - cotofix3D = 3, /* retrieved from a GPS with a 3D fix */ - cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */ + cotofix2D = 2, /* retrieved from a GPS with a 2D fix */ + cotofix3D = 3, /* retrieved from a GPS with a 3D fix */ + cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */ } fix_quality; struct record_track { @@ -54,21 +58,21 @@ struct record_track { word alt; /* Altitude */ /* accuracy and precision information for use where applicable */ - uword hdop; /* _dop * 10 */ - uword vdop; - uword pdop; + gbuint16 hdop; /* _dop * 10 */ + gbuint16 vdop; + gbuint16 pdop; ubyte sat_tracked; ubyte fix_quality; - uword speed; /* *10 */ - udword time; /* Palm Time */ + gbuint16 speed; /* *10 */ + gbuint32 time; /* Palm Time */ }; -#define MAX_MARKER_NAME_LENGTH 20 struct record_wpt { char lon[8]; char lat[8]; char name[MAX_MARKER_NAME_LENGTH]; + char notes[1]; }; @@ -76,29 +80,30 @@ struct record_wpt { typedef char appinfo_category[16]; -#define APPINFO_PACKED_SIZE sizeof(uword)+16*sizeof(appinfo_category)+17*sizeof(ubyte) -struct appinfo { - uword renamedCategories; - appinfo_category categories[16]; +typedef struct appinfo { + ubyte U0; + ubyte renamedCategories; + appinfo_category categories[CATEGORY_NAME_LENGTH]; ubyte ids[16]; ubyte maxid; -}; +} appinfo_t; + +#define APPINFO_SIZE sizeof(appinfo_t) static FILE *file_in; static FILE *file_out; static const char *out_fname; static const char *in_fname; /* We might need that for naming tracks */ static struct pdb *opdb; +static short_handle mkshort_wr_handle; -static char *trackname = NULL; static char *zerocat = NULL; static char *internals = NULL; static arglist_t coto_args[] = { - {"trackname", &trackname, "Track name", NULL, ARGTYPE_STRING }, {"zerocat", &zerocat, "Name of the 'unassigned' category.", NULL, ARGTYPE_STRING }, - {"internals", &internals, "Export some internal stuff to notes.", NULL, ARGTYPE_STRING|ARGTYPE_HIDDEN }, + {"internals", &internals, "Export some internal stuff to notes.", NULL, ARGTYPE_STRING | ARGTYPE_HIDDEN }, {0, 0, 0, 0, 0 } }; @@ -113,10 +118,6 @@ static void rd_deinit(void) { fclose(file_in); - if ( trackname ) { - xfree(trackname); - trackname = NULL; - } } static void @@ -130,10 +131,24 @@ static void wr_deinit(void) { fclose(file_out); - if ( trackname ) { - xfree(trackname); - trackname = NULL; +} + +/* helpers */ + +static char * +coto_get_icon_descr(int category, const appinfo_t *app) +{ + char buff[CATEGORY_NAME_LENGTH + 1] = "Not Assigned"; + if ((category >= 0) && (category < 16)) + { + if ((category > 0) && (app->categories[category][0] == '\0')) + category = 0; + + strncpy(buff, app->categories[category], sizeof(buff) - 1); + if (buff[0] == '\0') + return NULL; } + return xstrdup(buff); } static void @@ -142,43 +157,48 @@ coto_track_read(struct pdb *pdb) struct record_track *rec; struct pdb_record *pdb_rec; route_head *trk_head; - char *loctrackname = NULL; + char *track_name; - if (trackname) - // Given by user - loctrackname = xstrdup(trackname); - else if (strncmp(pdb->name, "cotoGPS TrackDB", PDB_DBNAMELEN)) + if (strncmp(pdb->name, "cotoGPS TrackDB", PDB_DBNAMELEN) != 0) // Use database name if not default - loctrackname = xstrndup(pdb->name, PDB_DBNAMELEN); + track_name = xstrndup(pdb->name, PDB_DBNAMELEN); else { - // Use filename - const char *fnametmp = strrchr(in_fname, '/'); // FIXME: Don't know if this works on Windows + // Use filename for new track title + const char *fnametmp = strrchr(in_fname, '/'); + if (fnametmp == NULL) + fnametmp = strrchr(in_fname, '\\'); if (fnametmp) fnametmp++; else fnametmp = in_fname; - loctrackname = xstrndup(fnametmp, strrchr(fnametmp,'.')-fnametmp); + if (strrchr(fnametmp, '.') != NULL) + track_name = xstrndup(fnametmp, strrchr(fnametmp,'.') - fnametmp); + else + track_name = xstrdup(fnametmp); } trk_head = route_head_alloc(); track_add_head(trk_head); - trk_head->rte_name = loctrackname; + trk_head->rte_name = track_name; - for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { + for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) + { waypoint *wpt_tmp; wpt_tmp = waypt_new(); rec = (struct record_track *) pdb_rec->data; - + wpt_tmp->longitude = -pdb_read_double(&rec->longitude)*360.0/(2.0*M_PI); wpt_tmp->latitude = pdb_read_double(&rec->latitude)*360.0/(2.0*M_PI); + // It's not the course, so leave it out for now // wpt_tmp->course = pdb_read_double(&rec->arc); wpt_tmp->altitude = be_read16(&rec->alt); - if (internals) { + if (internals) + { // Parse the option as xcsv delimiter const char *inter = xcsv_get_char_from_constant_table(internals); char temp[256]; @@ -191,20 +211,33 @@ coto_track_read(struct pdb *pdb) wpt_tmp->hdop = be_read16(&rec->hdop)/10.0; wpt_tmp->vdop = be_read16(&rec->vdop)/10.0; wpt_tmp->sat = rec->sat_tracked; - switch (rec->fix_quality) { - case cotofixNone: wpt_tmp->fix = fix_none; break; - case cotofixReserved: wpt_tmp->fix = fix_unknown; break; - case cotofix2D: wpt_tmp->fix = fix_2d; break; - case cotofix3D: wpt_tmp->fix = fix_3d; break; - case cotofixDGPS: wpt_tmp->fix = fix_dgps; break; + switch (rec->fix_quality) + { + case cotofixNone: + wpt_tmp->fix = fix_none; + break; + case cotofixReserved: + wpt_tmp->fix = fix_unknown; + break; + case cotofix2D: + wpt_tmp->fix = fix_2d; + break; + case cotofix3D: + wpt_tmp->fix = fix_3d; + break; + case cotofixDGPS: + wpt_tmp->fix = fix_dgps; + break; } wpt_tmp->speed = be_read16(&rec->speed)/10.0; - wpt_tmp->creation_time = be_read32(&rec->time) - 2082844800U; - + rec->time = be_read32(&rec->time); + if (rec->time != 0) + { + rec->time -= 2082844800U; + wpt_tmp->creation_time = rec->time; + } route_add_wpt(trk_head, wpt_tmp); - } - } static void @@ -212,43 +245,27 @@ coto_wpt_read(struct pdb *pdb) { struct record_wpt *rec; struct pdb_record *pdb_rec; - char *vdata; - struct appinfo *app; - + appinfo_t *app; app = (struct appinfo *) pdb->appinfo; - for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { + for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) + { waypoint *wpt_tmp; - int c=-1; wpt_tmp = waypt_new(); rec = (struct record_wpt *) pdb_rec->data; - // Find category - /* I thought this would be the proper way. Leaving it in in case it becomes the proper one =) - for(i=0;i<16;i++) - if (app->ids[i] == pdb_rec->category) {c=i; break;} - */ - c = pdb_rec->category; - wpt_tmp->longitude = -pdb_read_double(&rec->lon)*360.0/(2.0*M_PI); wpt_tmp->latitude = pdb_read_double(&rec->lat)*360.0/(2.0*M_PI); - wpt_tmp->shortname = xstrdup((char *) &rec->name); - wpt_tmp->description = xstrdup((char *) &rec->name); - - if (c>0) - wpt_tmp->icon_descr = xstrndup(app->categories[c], 16); - else if (c<0) - wpt_tmp->icon_descr = xstrdup("Unknown"); + wpt_tmp->shortname = xstrndup(rec->name, sizeof(rec->name)); + + wpt_tmp->icon_descr = coto_get_icon_descr(pdb_rec->category, app); if (wpt_tmp->icon_descr) wpt_tmp->wpt_flags.icon_descr_is_dynamic = 1; - if (pdb_rec->data_len>sizeof(*rec)) { - vdata = (char *) pdb_rec->data + sizeof(*rec); - wpt_tmp->notes = xstrdup(vdata); - } + wpt_tmp->notes = xstrdup(rec->notes); waypt_add(wpt_tmp); } @@ -268,14 +285,18 @@ data_read(void) fatal(MYNAME ": Not a cotoGPS file.\n"); } - if (pdb->version > 0) { - fatal(MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n"); - } + is_fatal((pdb->version > 0), + MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n"); - if (pdb->type == MYTYPETRACK) - coto_track_read(pdb); - if (pdb->type == MYTYPEWPT) - coto_wpt_read(pdb); + switch(pdb->type) + { + case MYTYPETRACK: + coto_track_read(pdb); + break; + case MYTYPEWPT: + coto_wpt_read(pdb); + break; + } free_pdb(pdb); } @@ -292,8 +313,8 @@ coto_prepare_wpt_write(struct pdb *opdb) strncpy(opdb->name, "cotoGPS MarkerDB", PDB_DBNAMELEN); - opdb->appinfo_len = APPINFO_PACKED_SIZE; - opdb->appinfo = calloc(APPINFO_PACKED_SIZE,1); + opdb->appinfo_len = APPINFO_SIZE; + opdb->appinfo = calloc(APPINFO_SIZE,1); ai = (struct appinfo *) opdb->appinfo; be_write16(&ai->renamedCategories, 31); // Don't ask me why... @@ -311,11 +332,9 @@ coto_wpt_write(const waypoint *wpt) struct appinfo *ai = (struct appinfo *) opdb->appinfo; static int ct; struct pdb_record *opdb_rec; - static short_handle mkshort_wr_handle; char *notes = NULL; char *shortname = NULL; - char *vdata; - int size = sizeof(*rec); + int size; ubyte cat = 0; int i; @@ -323,44 +342,49 @@ coto_wpt_write(const waypoint *wpt) setshort_length(mkshort_wr_handle, MAX_MARKER_NAME_LENGTH); setshort_whitespace_ok(mkshort_wr_handle, 1); - if ((global_opts.synthesize_shortnames && wpt->description) || (!wpt->shortname)) + if ((global_opts.synthesize_shortnames && wpt->description) || (wpt->shortname == NULL)) shortname = mkshort_from_wpt(mkshort_wr_handle, wpt); else shortname = xstrdup(wpt->shortname); - if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname)))) { - if ((wpt->notes) && (strcmp(wpt->description, wpt->notes))) { - size+=strlen(wpt->description)+strlen(wpt->notes)+9; - notes = xcalloc(strlen(wpt->description)+strlen(wpt->notes)+9,1); - sprintf(notes,"%s\nNotes:\n%s", wpt->description, wpt->notes); + if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname)))) + { + if ((wpt->notes) && (strcmp(wpt->description, wpt->notes) != 0)) + { + notes = xcalloc(strlen(wpt->description) + strlen(wpt->notes) + 9, 1); + sprintf(notes, "%s\nNotes:\n%s", wpt->description, wpt->notes); } else { - size+=strlen(wpt->description)+1; notes = xstrdup(wpt->description); } - } else if (wpt->notes) { - size+=strlen(wpt->notes)+1; + } + else if (wpt->notes != NULL) + { notes = xstrdup(wpt->notes); } - rec = xcalloc(size,1); + if (notes != NULL) + size += strlen(notes); + rec = xcalloc(size, 1); + pdb_write_double(&rec->lon, -2.0*M_PI*wpt->longitude/360.0); pdb_write_double(&rec->lat, 2.0*M_PI*wpt->latitude/360.0); - snprintf((char *) &rec->name, MAX_MARKER_NAME_LENGTH, "%s", shortname); + strncpy(rec->name, shortname, MAX_MARKER_NAME_LENGTH); - if (notes) { - vdata = (char *) rec + sizeof(*rec); - strcpy(vdata, notes); + if (notes) + { + strcpy(rec->notes, notes); xfree(notes); } - if (wpt->icon_descr) { - for(i=1;i<16;i++) + if (wpt->icon_descr) + { + for(i = 1; i < 16; i++) if (!strncmp(wpt->icon_descr, ai->categories[i], 16)) {cat=i; break;} if (!cat) { // We have a new one if (ai->maxid<15) { i = ++ai->maxid; snprintf(ai->categories[i], 16, "%s", wpt->icon_descr); - cat=ai->ids[i]=i; + cat = ai->ids[i] = i; } else { // We're full! warning(MYNAME ": Categories full. Category '%s' written as %s.\n", wpt->icon_descr, zerocat?zerocat:"Not Assigned"); @@ -370,18 +394,16 @@ coto_wpt_write(const waypoint *wpt) opdb_rec = new_Record (0, cat, ct++, size, (const ubyte *)rec); - if (opdb_rec == NULL) { + if (opdb_rec == NULL) fatal(MYNAME ": libpdb couldn't create record\n"); - } - if (pdb_AppendRecord(opdb, opdb_rec)) { + if (pdb_AppendRecord(opdb, opdb_rec)) fatal(MYNAME ": libpdb couldn't append record\n"); - } + xfree(shortname); xfree(rec); mkshort_del_handle(&mkshort_wr_handle); - } static void @@ -392,9 +414,14 @@ data_write(void) } coto_prepare_wpt_write(opdb); + waypt_disp_all(coto_wpt_write); + /* + if we want waypoints from all data, we should create a new filter for that + track_disp_all(NULL, NULL, coto_wpt_write); route_disp_all(NULL, NULL, coto_wpt_write); + */ pdb_Write(opdb, fileno(file_out)); diff --git a/gpsbabel/reference/cototestmarker.gpx b/gpsbabel/reference/cototestmarker.gpx index de942e558..1f04db89d 100644 --- a/gpsbabel/reference/cototestmarker.gpx +++ b/gpsbabel/reference/cototestmarker.gpx @@ -1,21 +1,21 @@ - + - + GC2663 - GC2663 + New Orleans Bon Chance (Good Luck) Cache-Cam by CrotalusRex and Mimichan New Orleans Bon Chance (Good Luck) Cache-Cam by CrotalusRex and Mimichan Geocache GCMK1V - GCMK1V + Randeck Maar Earthcache by Border Randeck Maar Earthcache by Border Earthcache diff --git a/gpsbabel/testo b/gpsbabel/testo index d3101d128..dd3100b7c 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -802,18 +802,20 @@ ${PNAME} -i gpx -f reference/dop-test.gpx -x discard,vdop=50 -o openoffice -F - compare ${TMPDIR}/dop-vdop.ref ${TMPDIR}/dop-vdop.fil # -# cotoGPS test +# cotoGPS tests # -# rm -f ${TMPDIR}/coto* +rm -f ${TMPDIR}/coto* # Track reading -# ${PNAME} -i coto -f reference/cototesttrack.pdb -o xcsv,style=reference/cototest.style -F ${TMPDIR}/cototrack.csv -# compare reference/cototesttrack.csv ${TMPDIR}/cototrack.csv -# Marker read/write -# ${PNAME} -i coto -f reference/cototestmarker.pdb -o xcsv,style=reference/cototest.style -F ${TMPDIR}/cotomarker.csv -# ${PNAME} -i gpx -f reference/cototestmarker.gpx -o xcsv,style=reference/cototest.style -F ${TMPDIR}/cotomarkergpx.csv -# compare ${TMPDIR}/cotomarker.csv ${TMPDIR}/cotomarkergpx.csv -# ${PNAME} -i gpx -f reference/cototestmarker.gpx -o coto -F ${TMPDIR}/cotomarker.pdb -# compare reference/cototestmarker.pdb ${TMPDIR}/cotomarker.pdb +${PNAME} -i coto -f reference/cototesttrack.pdb -o xcsv,style=reference/cototest.style -F ${TMPDIR}/cototrack.csv +compare reference/cototesttrack.csv ${TMPDIR}/cototrack.csv +# Marker read +${PNAME} -i coto -f reference/cototestmarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx +compare reference/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx +# Marker write +${PNAME} -i gpx -f reference/cototestmarker.gpx -o coto -F ${TMPDIR}/cotomarker.pdb +# bincompare reference/cototestmarker.pdb ${TMPDIR}/cotomarker.pdb +${PNAME} -i coto -f ${TMPDIR}/cotomarker.pdb -o gpx -F ${TMPDIR}/cotomarker.gpx +compare reference/cototestmarker.gpx ${TMPDIR}/cotomarker.gpx # # Fugawi test cases diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index cbd6cd1a2..df3317261 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -433,14 +433,12 @@ vecs_t vec_list[] = { "Motorrad Routenplaner (Map&Guide) .bcr files", "bcr" }, -#if 0 { &coto_vecs, "coto", "cotoGPS for Palm/OS", "pdb" }, -#endif { &ignr_vecs, "ignrando", -- 2.30.2